home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Medal Software 1
/
Gold Medal Software Volume 1 (Gold Medal) (1994).iso
/
graphics
/
povsrc20.arj
/
SOURCE
/
VECT.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-10-03
|
26KB
|
994 lines
/****************************************************************************
* vect.c
*
* This file was written by Alexander Enzmann. He wrote the code for
* 4th-6th order shapes and generously provided us these enhancements.
*
* from Persistence of Vision Raytracer
* Copyright 1993 Persistence of Vision Team
*---------------------------------------------------------------------------
* NOTICE: This source code file is provided so that users may experiment
* with enhancements to POV-Ray and to port the software to platforms other
* than those supported by the POV-Ray Team. There are strict rules under
* which you are permitted to use this file. The rules are in the file
* named POVLEGAL.DOC which should be distributed with this file. If
* POVLEGAL.DOC is not available or for more info please contact the POV-Ray
* Team Coordinator by leaving a message in CompuServe's Graphics Developer's
* Forum. The latest version of POV-Ray may be found there as well.
*
* This program is based on the popular DKB raytracer version 2.12.
* DKBTrace was originally written by David K. Buck.
* DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
*
*****************************************************************************/
#include "frame.h"
#include "povproto.h"
#include "vector.h"
#ifdef ABS
#undef ABS
#endif
#ifdef MAX
#undef MAX
#endif
extern int Shadow_Test_Flag;
#undef EPSILON
#define EPSILON 1.0e-10
#define COEFF_LIMIT 1.0e-20
/* WARNING WARNING WARNING
The following three constants have been defined so that quartic equations
will properly render on fpu/compiler combinations that only have 64 bit
IEEE precision. Do not arbitrarily change any of these values.
If you have a machine with a proper fpu/compiler combo - like a Mac with
a 68881, then use the native floating format (96 bits) and tune the
values for a little less tolerance: something like: factor1 = 1.0e15,
factor2 = -1.0e-7, factor3 = 1.0e-10.
The meaning of the three constants are:
factor1 - the magnitude of difference between coefficients in a
quartic equation at which the Sturmian root solver will
kick in. The Sturm solver is quite a bit slower than
the algebraic solver, so the bigger this is, the faster
the root solving will go. The algebraic solver is less
accurate so the bigger this is, the more likely you will
get bad roots.
factor2 - Tolerance value that defines how close the quartic equation
is to being a square of a quadratic. The closer this can
get to zero before roots disappear, the less the chance
you will get spurious roots.
factor3 - Similar to factor2 at a later stage of the algebraic solver.
*/
#define FUDGE_FACTOR1 1.0e12
#define FUDGE_FACTOR2 -1.0e-5
#define FUDGE_FACTOR3 1.0e-7
#define ABS(x) ((x) < 0.0 ? (0.0 - x) : (x))
#define MAX(x,y) (x<y?y:x)
#define TWO_PI 6.283185207179586476925286766560
#define TWO_PI_3 2.0943951023931954923084
#define TWO_PI_43 4.1887902047863909846168
#define MAX_ITERATIONS 50
#define MAXPOW 32
typedef struct p {
int ord;
DBL coef[MAX_ORDER+1];
}
polynomial;
static int modp PARAMS((polynomial *u, polynomial *v, polynomial *r));
int regula_falsa PARAMS((int order, DBL *coef, DBL a, DBL b, DBL *val));
static int sbisect PARAMS((int np, polynomial *sseq, DBL min, DBL max, int atmin, int atmax, DBL *roots));
int numchanges PARAMS((int np, polynomial *sseq, DBL a));
DBL polyeval PARAMS((DBL x, int n, DBL *Coeffs));
int buildsturm PARAMS((int ord, polynomial *sseq));
int visible_roots PARAMS((int np, polynomial *sseq, int *atneg, int *atpos));
static int difficult_coeffs PARAMS((int n, DBL *x));
/*
* modp
*
* calculates the modulus of u(x) / v(x) leaving it in r, it
* returns 0 if r(x) is a constant.
* note: this function assumes the leading coefficient of v
* is 1 or -1
*/
static int modp(u, v, r)
polynomial *u, *v, *r;
{
int i, k, j;
for (i=0;i<u->ord;i++)
r[i] = u[i];
if (v->coef[v->ord] < 0.0)
{
for (k = u->ord - v->ord - 1; k >= 0; k -= 2)
r->coef[k] = -r->coef[k];
for (k = u->ord - v->ord; k >= 0; k--)
for (j = v->ord + k - 1; j >= k; j--)
r->coef[j] = -r->coef[j] - r->coef[v->ord + k] * v->coef[j - k];
}
else
{
for (k = u->ord - v->ord; k >= 0; k--)
for (j = v->ord + k - 1; j >= k; j--)
r->coef[j] -= r->coef[v->ord + k] * v->coef[j - k];
}
k = v->ord - 1;
while (k >= 0 && fabs(r->coef[k]) < COEFF_LIMIT)
{
r->coef[k] = 0.0;
k--;
}
r->ord = (k < 0) ? 0 : k;
return(r->ord);
}
/* Build the sturmian sequence for a polynomial */
int buildsturm(ord, sseq)
int ord;
polynomial *sseq;
{
int i;
DBL f, *fp, *fc;
polynomial *sp;
sseq[0].ord = ord;
sseq[1].ord = ord - 1;
/* calculate the derivative and normalize the leading coefficient. */
f = fabs(sseq[0].coef[ord] * ord);
fp = sseq[1].coef;
fc = sseq[0].coef + 1;
for (i = 1; i <= ord; i++)
*fp++ = *fc++ * i / f;
/* construct the rest of the Sturm sequence */
for (sp = sseq + 2;modp(sp - 2, sp - 1, sp); sp++)
{
/* reverse the sign and normalize */
f = -fabs(sp->coef[sp->ord]);
for (fp = &sp->coef[sp->ord]; fp >= sp->coef; fp--)
*fp /= f;
}
sp->coef[0] = -sp->coef[0]; /* reverse the sign */
return(sp - sseq);
}
/* Find out how many visible intersections there are */
int visible_roots(np, sseq, atzer, atpos)
int np;
polynomial *sseq;
int *atzer, *atpos;
{
int atposinf, atzero;
polynomial *s;
DBL f, lf;
atposinf = atzero = 0;
/* changes at positve infinity */
lf = sseq[0].coef[sseq[0].ord];
for (s = sseq + 1; s <= sseq + np; s++)
{
f = s->coef[s->ord];
if (lf == 0.0 || lf * f < 0)
atposinf++;
lf = f;
}
/* Changes at zero */
lf = sseq[0].coef[0];
for (s = sseq+1; s <= sseq + np; s++)
{
f = s->coef[0];
if (lf == 0.0 || lf * f < 0)
atzero++;
lf = f;
}
*atzer = atzero;
*atpos = atposinf;
return(atzero - atposinf);
}
/*
* numchanges
*
* return the number of sign changes in the Sturm sequence in
* sseq at the value a.
*/
int numchanges(np, sseq, a)
int np;
polynomial *sseq;
DBL a;
{
int changes;
DBL f, lf;
polynomial *s;
changes = 0;
COOPERATE
lf = polyeval(a, sseq[0].ord, sseq[0].coef);
for (s = sseq + 1; s <= sseq + np; s++)
{
f = polyeval(a, s->ord, s->coef);
if (lf == 0.0 || lf * f < 0)
changes++;
lf = f;
}
return(changes);
}
/*
* sbisect
*
* uses a bisection based on the sturm sequence for the polynomial
* described in sseq to isolate intervals in which roots occur,
* the roots are returned in the roots array in order of magnitude.
Note: This routine has one severe bug: When the interval containing the
root [min, max] has a root at one of its endpoints, as well as one
within the interval, the root at the endpoint will be returned rather
than the one inside.
*/
static int
sbisect(np, sseq, min_value, max_value, atmin, atmax, roots)
int np;
polynomial *sseq;
DBL min_value, max_value;
int atmin, atmax;
DBL *roots;
{
DBL mid;
int n1, n2, its, atmid;
if ((atmin - atmax) == 1)
{
/* first try using regula-falsa to find the root. */
if (regula_falsa(sseq->ord, sseq->coef, min_value, max_value, roots))
return 1;
else
{
/* That failed, so now find it by bisection */
for (its = 0; its < MAX_ITERATIONS; its++)
{
mid = (min_value + max_value) / 2;
atmid = numchanges(np, sseq, mid);
if (fabs(mid) > EPSILON)
{
if (fabs((max_value - min_value) / mid) < EPSILON)
{
roots[0] = mid;
return 1;
}
}
else if (fabs(max_value - min_value) < EPSILON)
{
roots[0] = mid;
return 1;
}
else if ((atmin - atmid) == 0)
min_value = mid;
else
max_value = mid;
}
/* Bisection took too long - just return what we got */
roots[0] = mid;
return 1;
}
}
/* There is more than one root in the interval.
Bisect to find new intervals */
for (its = 0; its < MAX_ITERATIONS; its++)
{
mid = (min_value + max_value) / 2;
atmid = numchanges(np, sseq, mid);
n1 = atmin - atmid;
n2 = atmid - atmax;
if (n1 != 0 && n2 != 0)
{
n1 = sbisect(np, sseq, min_value, mid, atmin, atmid, roots);
n2 = sbisect(np, sseq, mid, max_value, atmid, atmax, &roots[n1]);
return n1 + n2;
}
if (n1 == 0)
min_value = mid;
else
max_value = mid;
}
/* Took too long to bisect. Just return what we got. */
roots[0] = mid;
return 1;
}
DBL polyeval(x, n, Coeffs)
DBL x, *Coeffs;
int n;
{
register int i;
DBL val;
val = Coeffs[n];
for (i=n-1;i>=0;i--) val = val * x + Coeffs[i];
return val;
}
/* Close in on a root by using regula-falsa */
int regula_falsa(order, coef, a, b, val)
int order;
DBL *coef;
DBL a, b, *val;
{
int its;
DBL fa, fb, x, fx, lfx;
fa = polyeval(a, order, coef);
fb = polyeval(b, order, coef);
if (fa * fb > 0.0)
return 0;
if (fabs(fa) < COEFF_LIMIT)
{
*val = a;
return 1;
}
if (fabs(fb) < COEFF_LIMIT)
{
*val = b;
return 1;
}
lfx = fa;
COOPERATE
for (its = 0; its < MAX_ITERATIONS; its++)
{
x = (fb * a - fa * b) / (fb - fa);
fx = polyeval(x, order, coef);
if (fabs(x) > EPSILON)
{
if (fabs(fx / x) < EPSILON)
{
*val = x;
return 1;
}
}
else if (fabs(fx) < EPSILON)
{
*val = x;
return 1;
}
if (fa < 0)
if (fx < 0)
{
a = x;
fa = fx;
if ((lfx * fx) > 0)
fb /= 2;
}
else
{
b = x;
fb = fx;
if ((lfx * fx) > 0)
fa /= 2;
}
else if (fx < 0)
{
b = x;
fb = fx;
if ((lfx * fx) > 0)
fa /= 2;
}
else
{
a = x;
fa = fx;
if ((lfx * fx) > 0)
fb /= 2;
}
if (fabs(b-a) < EPSILON)
{
/* Check for underflow in the domain */
*val = x;
return 1;
}
lfx = fx;
}
return 0;
}
/*
Solve the quadratic equation:
x[0] * x^2 + x[1] * x + x[2] = 0.
The value returned by this function is the number of real roots.
The roots themselves are returned in y[0], y[1].
*/
int solve_quadratic(x, y)
DBL *x, *y;
{
DBL d, t, a, b, c;
a = x[0];
b = -x[1];
c = x[2];
if (a == 0.0)
{
if (b == 0.0)
return 0;
y[0] = c / b;
return 1;
}
d = b * b - 4.0 * a * c;
if (d < 0.0)
return 0;
else if (fabs(d) < COEFF_LIMIT)
{
y[0] = 0.5 * b / a;
return 1;
}
d = sqrt(d);
t = 2.0 * a;
y[0] = (b + d) / t;
y[1] = (b - d) / t;
return 2;
}
/*
Solve the cubic equation:
x[0] * x^3 + x[1] * x^2 + x[2] * x + x[3] = 0.
The result of this function is an integer that tells how many real
roots exist. Determination of how many are distinct is up to the
process that calls this routine. The roots that exist are stored
in (y[0], y[1], y[2]).
Note: this function relies very heavily on trigonometric functions and
the square root function. If an alternative solution is found that does
not rely on transcendentals this code will be replaced.
*/
int solve_cubic(x, y)
DBL *x, *y;
{
DBL Q, R, Q3, R2, sQ, d, an, theta;
DBL A2, a0, a1, a2, a3;
a0 = x[0];
if (a0 == 0.0) return solve_quadratic(&x[1], y);
else if (a0 != 1.0)
{
a1 = x[1] / a0;
a2 = x[2] / a0;
a3 = x[3] / a0;
}
else
{
a1 = x[1];
a2 = x[2];
a3 = x[3];
}
A2 = a1 * a1;
Q = (A2 - 3.0 * a2) / 9.0;
R = (2.0 * A2 * a1 - 9.0 * a1 * a2 + 27.0 * a3) / 54.0;
Q3 = Q * Q * Q;
R2 = R * R;
d = Q3 - R2;
an = a1 / 3.0;
if (d >= 0.0)
{
/* Three real roots. */
d = R / sqrt(Q3);
theta = acos(d) / 3.0;
sQ = -2.0 * sqrt(Q);
y[0] = sQ * cos(theta) - an;
y[1] = sQ * cos(theta + TWO_PI_3) - an;
y[2] = sQ * cos(theta + TWO_PI_43) - an;
return 3;
}
else
{
sQ = pow(sqrt(R2 - Q3) + ABS(R), 1.0 / 3.0);
if (R < 0)
y[0] = (sQ + Q / sQ) - an;
else
y[0] = -(sQ + Q / sQ) - an;
return 1;
}
}
/* Test to see if any coeffs are more than 6 orders of magnitude
larger than the smallest */
static int
difficult_coeffs(n, x)
int n;
DBL *x;
{
int i, flag = 0;
DBL t, biggest;
biggest = fabs(x[0]);
for (i=1;i<=n;i++)
{
t = fabs(x[i]);
if (t > biggest)
biggest = t;
}
/* Everything is zero no sense in doing any more */
if (biggest == 0.0) return 0;
for (i=0;i<=n;i++)
if (x[i] != 0.0)
if (fabs(biggest / x[i]) > FUDGE_FACTOR1)
{
x[i] = 0.0;
flag = 1;
}
return flag;
}
#ifdef TEST_SOLVER
/* The old way of solving quartics algebraically */
/* This is an adaptation of the method of Lodovico Ferrari (Circa 1731). */
int solve_quartic(x, results)
DBL *x, *results;
{
DBL cubic[4], roots[3];
DBL a0, a1, y, d1, x1, t1, t2;
DBL c0, c1, c2, c3, c4, d2, q1, q2;
int i;
/* Figure out the size difference between coefficients */
if (difficult_coeffs(4, x))
{
if (fabs(x[0]) < COEFF_LIMIT)
if (fabs(x[1]) < COEFF_LIMIT)
return solve_quadratic(&x[2], results);
else
return solve_cubic(&x[1], results);
else
return polysolve(4, x, results);
}
c0 = x[0];
if (fabs(c0) < COEFF_LIMIT)
return solve_cubic(&x[1], results);
else if (fabs(x[4]) < COEFF_LIMIT)
{
return solve_cubic(x, results);
}
else if (c0 != 1.0)
{
c1 = x[1] / c0;
c2 = x[2] / c0;
c3 = x[3] / c0;
c4 = x[4] / c0;
}
else
{
c1 = x[1];
c2 = x[2];
c3 = x[3];
c4 = x[4];
}
/* The first step is to take the original equation:
x^4 + b*x^3 + c*x^2 + d*x + e = 0
and rewrite it as:
x^4 + b*x^3 = -c*x^2 - d*x - e,
adding (b*x/2)^2 + (x^2 + b*x/2)y + y^2/4 to each side gives a
perfect square on the lhs:
(x^2 + b*x/2 + y/2)^2 = (b^2/4 - c + y)x^2 + (b*y/2 - d)x + y^2/4 - e
By choosing the appropriate value for y, the rhs can be made a perfect
square also. This value is found when the rhs is treated as a quadratic
in x with the discriminant equal to 0. This will be true when:
(b*y/2 - d)^2 - 4.0 * (b^2/4 - c*y)*(y^2/4 - e) = 0, or
y^3 - c*y^2 + (b*d - 4*e)*y - b^2*e + 4*c*e - d^2 = 0.
This is called the resolvent of the quartic equation. */
a0 = 4.0 * c4;
cubic[0] = 1.0;
cubic[1] = -1.0 * c2;
cubic[2] = c1 * c3 - a0;
cubic[3] = a0 * c2 - c1 * c1 * c4 - c3 * c3;
i = solve_cubic(&cubic[0], &roots[0]);
if (i > 0)
y = roots[0];
else
return 0;
/* What we are left with is a quadratic squared on the lhs and a
linear term on the right. The linear term has one of two signs,
take each and add it to the lhs. The form of the quartic is now:
a' = b^2/4 - c + y, b' = b*y/2 - d, (from rhs quadritic above)
(x^2 + b*x/2 + y/2) = +sqrt(a'*(x + 1/2 * b'/a')^2), and
(x^2 + b*x/2 + y/2) = -sqrt(a'*(x + 1/2 * b'/a')^2).
By taking the linear term from each of the right hand sides and
adding to the appropriate part of the left hand side, two quadratic
formulas are created. By solving each of these the four roots of
the quartic are determined.
*/
i = 0;
a0 = c1 / 2.0;
a1 = y / 2.0;
t1 = a0 * a0 - c2 + y;
if (t1 < 0.0)
{
if (t1 > FUDGE_FACTOR2)
t1 = 0.0;
else
{
/* First Special case, a' < 0 means all roots are complex. */
return 0;
}
}
if (t1 < FUDGE_FACTOR3)
{
/* Second special case, the "x" term on the right hand side above
has vanished. In this case:
(x^2 + b*x/2 + y/2) = +sqrt(y^2/4 - e), and
(x^2 + b*x/2 + y/2) = -sqrt(y^2/4 - e). */
t2 = a1 * a1 - c4;
if (t2 < 0.0)
{
return 0;
}
x1 = 0.0;
d1 = sqrt(t2);
}
else
{
x1 = sqrt(t1);
d1 = 0.5 * (a0 * y - c3) / x1;
}
/* Solve the first quadratic */
q1 = -a0 - x1;
q2 = a1 + d1;
d2 = q1 * q1 - 4.0 * q2;
if (d2 >= 0.0)
{
d2 = sqrt(d2);
results[0] = 0.5 * (q1 + d2);
results[1] = 0.5 * (q1 - d2);
i = 2;
}
/* Solve the second quadratic */
q1 = q1 + x1 + x1;
q2 = a1 - d1;
d2 = q1 * q1 - 4.0 * q2;
if (d2 >= 0.0)
{
d2 = sqrt(d2);
results[i++] = 0.5 * (q1 + d2);
results[i++] = 0.5 * (q1 - d2);
}
return i;
}
#else
/* Solve a quartic using the method of Francois Vieta (Circa 1735) */
int
solve_quartic(x, results)
DBL *x, *results;
{
DBL cubic[4], roots[3];
DBL c12, z, p, q, q1, q2, r, d1, d2;
DBL c0, c1, c2, c3, c4;
int i;
/* Figure out the size difference between coefficients */
if (difficult_coeffs(4, x))
{
if (fabs(x[0]) < COEFF_LIMIT)
if (fabs(x[1]) < COEFF_LIMIT)
return solve_quadratic(&x[2], results);
else
return solve_cubic(&x[1], results);
else
return polysolve(4, x, results);
}
/* See if the high order term has vanished */
c0 = x[0];
if (fabs(c0) < COEFF_LIMIT)
return solve_cubic(&x[1], results);
/* See if the constant term has vanished */
if (fabs(x[4]) < COEFF_LIMIT)
return solve_cubic(x, results);
/* Make sure the quartic has a leading coefficient of 1.0 */
if (c0 != 1.0)
{
c1 = x[1] / c0;
c2 = x[2] / c0;
c3 = x[3] / c0;
c4 = x[4] / c0;
}
else
{
c1 = x[1];
c2 = x[2];
c3 = x[3];
c4 = x[4];
}
/* Compute the cubic resolvant */
c12 = c1 * c1;
p = -0.375 * c12 + c2;
q = 0.125 * c12 * c1 - 0.5 * c1 * c2 + c3;
r = -0.01171875 * c12 * c12 + 0.0625 * c12 * c2 - 0.25 * c1 * c3 + c4;
cubic[0] = 1.0;
cubic[1] = -0.5 * p;
cubic[2] = -r;
cubic[3] = 0.5 * r * p - 0.125 * q * q;
i = solve_cubic(cubic, roots);
if (i > 0)
z = roots[0];
else
return 0;
d1 = 2.0 * z - p;
if (d1 < 0.0)
{
if (d1 > -EPSILON)
d1 = 0.0;
else
return 0;
}
if (d1 < EPSILON)
{
d2 = z * z - r;
if (d2 < 0.0)
return 0;
d2 = sqrt(d2);
}
else
{
d1 = sqrt(d1);
d2 = 0.5 * q / d1;
}
/* Set up useful values for the quadratic factors */
q1 = d1 * d1;
q2 = -0.25 * c1;
i = 0;
/* Solve the first quadratic */
p = q1 - 4.0 * (z - d2);
if (p == 0)
results[i++] = -0.5 * d1 - q2;
else if (p > 0)
{
p = sqrt(p);
results[i++] = -0.5 * (d1 + p) + q2;
results[i++] = -0.5 * (d1 - p) + q2;
}
/* Solve the second quadratic */
p = q1 - 4.0 * (z + d2);
if (p == 0)
results[i++] = 0.5 * d1 - q2;
else if (p > 0)
{
p = sqrt(p);
results[i++] = 0.5 * (d1 + p) + q2;
results[i++] = 0.5 * (d1 - p) + q2;
}
return i;
}
#endif
/* Root solver based on the Sturm sequences for a polynomial. */
int polysolve(order, Coeffs, roots)
int order;
DBL *Coeffs, *roots;
{
polynomial sseq[MAX_ORDER+1];
DBL min_value, max_value;
int i, nroots, np, atmin, atmax;
/* Put the coefficients into the top of the stack. */
for (i=0;i<=order;i++)
sseq[0].coef[order-i] = Coeffs[i];
/* Build the Sturm sequence */
np = buildsturm(order, &sseq[0]);
/* Get the total number of visible roots */
if ((nroots = visible_roots(np, sseq, &atmin, &atmax)) == 0)
return 0;
/* Bracket the roots */
min_value = 0.0;
max_value = Max_Distance;
atmin = numchanges(np, sseq, min_value);
atmax = numchanges(np, sseq, max_value);
nroots = atmin - atmax;
if (nroots == 0) return 0;
/* perform the bisection. */
return sbisect(np, sseq, min_value, max_value, atmin, atmax, roots);
}
#ifdef TEST /* This is not used anywhere or tested. Interesting? */
#define MAX_POLYGON_SIDES 8
#define Crossing_Point(x1, y1, x2, y2) (x1 - y1 * (x2 - x1) / (y2 - y1))
/* See if "Ray" intersects the polygon defined by the coordinate list "vertices". */
int Intersect_Polygon(Ray, vertex_count, vertices, n, d, Depth, Intersect_Point)
RAY *Ray;
int vertex_count;
VECTOR *vertices, *n, *Intersect_Point;
DBL d, *Depth;
{
DBL s, t, x, y, z;
int Sign_Holder, Next_Sign, Crossings;
int i, this_vertex, next_vertex;
static DBL temp_x[MAX_POLYGON_SIDES],
temp_y[MAX_POLYGON_SIDES];
/* Calculate the point of intersection and the depth. */
VDot(s, Ray->Direction, *n);
if (s == 0.0)
return 0;
VDot(t, Ray->Initial, *n);
*Depth = 0.0 - (d + t) / s;
if (*Depth < Small_Tolerance)
return 0;
VScale(*Intersect_Point, Ray->Direction, *Depth);
VAdd(*Intersect_Point, *Intersect_Point, Ray->Initial);
/* Map the intersection point and the triangle onto a plane. */
x = ABS(n->x); y = ABS(n->y); z = ABS(n->z);
if (x>y)
if (x>z)
for (i=0;i<vertex_count;i++)
{
temp_x[i] = vertices[i].y - Intersect_Point->y;
temp_y[i] = vertices[i].z - Intersect_Point->z;
}
else
for (i=0;i<vertex_count;i++)
{
temp_x[i] = vertices[i].x - Intersect_Point->x;
temp_y[i] = vertices[i].y - Intersect_Point->y;
}
else if (y>z)
for (i=0;i<vertex_count;i++)
{
temp_x[i] = vertices[i].x - Intersect_Point->x;
temp_y[i] = vertices[i].z - Intersect_Point->z;
}
else
for (i=0;i<vertex_count;i++)
{
temp_x[i] = vertices[i].x - Intersect_Point->x;
temp_y[i] = vertices[i].y - Intersect_Point->y;
}
/* Determine crossing count */
Crossings = 0;
if (temp_y[0] < 0) Sign_Holder = -1;
else Sign_Holder = 1;
for (i=0;i<vertex_count;i++)
{
/* Start of winding tests, test the segment from v1 to v2 */
this_vertex = i;
next_vertex = (i + 1) % vertex_count;
if (temp_y[next_vertex] < 0) Next_Sign = -1;
else Next_Sign = 1;
if (Sign_Holder != Next_Sign)
{
if (temp_x[this_vertex] > 0.0)
{
if (temp_x[next_vertex] > 0.0)
Crossings++;
else if (Crossing_Point(temp_x[this_vertex], temp_y[this_vertex],
temp_x[next_vertex], temp_y[next_vertex]) > 0.0)
Crossings++;
}
else if (temp_x[next_vertex] > 0.0)
{
if (Crossing_Point(temp_x[this_vertex], temp_y[this_vertex],
temp_x[next_vertex], temp_y[next_vertex]) > 0.0)
Crossings++;
}
Sign_Holder = Next_Sign;
}
}
return (Crossings&1); /* Inside only if # of crossings odd. */
}
/* Translate screen coordinates into world coordinates. */
void World_Coordinate (Viewpoint, Ray, width, height, x, y)
VIEWPOINT *Viewpoint;
RAY *Ray;
int width, height;
DBL x, y;
{
DBL scalex, scaley;
VECTOR V1, V2;
/* Convert the X Coordinate to be a DBL from -0.5 to 0.5 */
scalex = (x - (DBL)width / 2.0) / (DBL)width;
/* Convert the Y Coordinate to be a DBL from -0.5 to 0.5 */
scaley = (((DBL)(height - 1) - y) - (DBL)height / 2.0) / (DBL)height;
/* Compute the direction of the screen point from the viewpoint */
VScale (V1, Viewpoint->Up, scaley);
VScale (V2, Viewpoint->Right, scalex);
VAdd (Ray->Direction, V1, V2);
VAdd (Ray->Direction, Ray->Direction, Viewpoint->Direction);
VNormalize (Ray->Direction, Ray->Direction);
}
/* Uncomment these two declarations if your compiler needs them */
/* They give Microsoft C an out of macro expansion space error */
/* void show_univariate_poly PARAMS((char *label, int order,DBL *Coeffs)); */
/* void show_points PARAMS((char *label,int count,DBL *point_list); */
void show_univariate_poly(label, order, Coeffs)
char *label;
int order;
DBL *Coeffs;
{
int i;
printf("%s", label);
for (i=0;i<=order;i++)
{
printf("%.2lf x^%d", Coeffs[i], order-i);
if (i==order) printf("\n");
else printf(" + ");
}
}
void show_points(label, count, point_list)
char *label;
int count;
DBL *point_list;
{
int i;
printf("%s", label);
for (i=0;i<count;i++)
{
printf("%lf", point_list[i]);
if (i==(count-1)) printf("\n");
else printf(", ");
}
}
#endif